package com.xxx.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import com.xxx.annotation.RateLimiterAnno;
import com.xxx.ratelimiter.CounterLimiter;
import com.xxx.ratelimiter.RedisLimiter;
import com.xxx.ratelimiter.SlideWindowLimiter;
import com.xxx.util.JedisUtil;
import com.xxx.util.JodaUtil;

/**
 * 测试限流器
 */
@RestController
@RequestMapping("/api")
public class RateLimiterController extends BaseController {
	
	private static final Logger logger = LoggerFactory.getLogger(RateLimiterController.class);
    
    /**
     * 测试api限流
     * http://localhost/api/apiRestrict
     */
    @RequestMapping("/apiRestrict")
    public ModelAndView apiRestrict(){
    	ModelAndView mav = new ModelAndView(new MappingJackson2JsonView());
    	
    	// 测试redis限流方案一：借助redis计数器限流
    	try {
    		RedisLimiter.checkLimit1("api1", 10, 60);  // 模拟60秒内最多可以调用10次api
        	long len = JedisUtil.llen("checkLimit1:api1");
        	mav.addObject("invoked times：", len);
    	} catch (Exception e) {
    		mav.addObject("error", "超过限流阀值!!!");
    	}
    	return mav;
    	
    	// 测试redis限流方案二：借助redis计数器限流
//    	try {
//    		RedisLimiter.checkLimit2("api2", 10, 60); // 模拟60秒内最多可以调用10次api
//    		String cnt = JedisUtil.get("checkLimit2:api2");
//    		mav.addObject("invoked times：", cnt);
//    	} catch (Exception e) {
//    		mav.addObject("error", "超过限流阀值!!!");
//    	}
//    	return mav;
    	// 以上是借助第三方组件redis进行限流，限制的是整个集群（也可以对每个节点进行单独限流）
    	
    	// 测试限流方案三：本地计数器算法
//    	if(CounterLimiter.checkLimit()) {
//    		mav.addObject("invoked times：", CounterLimiter.reqCount);
//    	} else {
//    		mav.addObject("error", "超过限流阀值!!!");
//    	}
//    	return mav;
    	// 此方案不借助第三方组件，可以对单个节点进行限流
    	
//    	// 测试限流方案四：滑动窗口算法
//    	if(SlideWindowLimiter.slideWindowLimit("api3")) {
//    		mav.addObject("current invoked times：", SlideWindowLimiter.getCurrInvokeTimes("api3"));
//    		mav.addObject("total invoked times：", SlideWindowLimiter.getTotalInvokeTimes("api3"));
//    	} else {
//    		mav.addObject("error", "超过限流阀值!!!");
//    	}
//    	return mav;
    }
    
    /**
     * 测试guava令牌桶算法限流器
     * http://localhost/api/getServerTime
     */
	@RateLimiterAnno(apiKey="getServerTime", type=RateLimiterAnno.TYPE.IP, permits=2) // 按ip限流，每个ip每秒最多能请求2次
    @RequestMapping("/getServerTime")
    public ModelAndView getServerTime(){
    	logger.info("enter method getServerTime().");
    	ModelAndView mav = new ModelAndView(new MappingJackson2JsonView());
    	mav.addObject("serverTime", JodaUtil.currentTime());
        return mav;
    }
    
}
